package com.brower.project.base

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.brower.project.BaseApplication
import com.brower.project.net.RetrofitClient
import com.brower.project.net.CommonApiService
import com.brower.project.net.bean.BaseResponse
import com.brower.project.utils.NetWorkUtils
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.launch

open class BaseViewModel : ViewModel() {
    val uiChange: UIChange by lazy { UIChange() }
    val service by lazy { RetrofitClient().getService(CommonApiService::class.java) }

    /**
     * 过滤请求结果，其他全抛异常
     * @param request 请求体
     * @param resp 成功回调 响应
     * @param error 失败回调
     * @param complete  完成回调（无论成功失败都会调用）
     */
    fun <T> launchFlow(
        request: suspend CoroutineScope.() -> BaseResponse<T>,
        resp: (T?) -> Unit,
        error: (String) -> Unit = {},
        complete: () -> Unit = {}
    ) {
        //请求之前操作
        if (prepare()) {
            complete()
            return
        }
        viewModelScope.launch {
            flow { emit(request()) }//网络请求
                .flowOn(Dispatchers.IO)//指定线程
                .catch {//异常捕获
                    error(it.message ?: "")   //有基类自行处理,业务层也可以自行处理
                    showToast(it.message ?: "")
                    complete()
                }
                .collect {//数据回调
                    handlerCode(it, resp, error)
                    complete()
                }
        }
    }

    /**
     * 请求之前操作
     */
    private fun prepare(): Boolean {
        //网络监测
        if (!NetWorkUtils.isNetworkAvailable(BaseApplication.CONTEXT)) {
            //关闭页面loading
            showToast("网络异常")
            return true
        }
        return false
    }

    /**
     * 响应处理
     */
    private fun <T> handlerCode(
        it: BaseResponse<T>,
        resp: (T?) -> Unit,
        error: (String) -> Unit
    ) {
        when (it.errorCode) {     //网络响应解析
            0 -> {
                resp(it.data)  //数据加载完成交由业务层处理
            }
            else -> {
                error(it.errorMsg)
                showToast(it.errorMsg)
            }
        }
    }


    fun finish() {
        uiChange.finish.postValue(FinishData(true))
    }

    fun showToast(text: String) {
        uiChange.toast.postValue(text)
    }

    fun showLoadView() {
        uiChange.showLoadView.postValue(true)
    }

    fun dismissLoadView() {
        uiChange.dismissLoadView.postValue(true)
    }
}